﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using Fuse8.ContentManagementFramework.Web.Etc.PagePresent;
using Fuse8.ContentManagementFramework.Web.MvcPowered.Components.Models;
using Fuse8.DomainFramework.Common;
using Fuse8.DomainFramework.Common.Locator;

using Fuse8.ContentManagementFramework.Domain;
using Fuse8.ContentManagementFramework.BizFacade.Services;
using Fuse8.ContentManagementFramework.Domain.Special;

namespace Fuse8.ContentManagementFramework.Web.MvcPowered
{
    public static class CmsPageBreadcrumbsHtmlHelperExtension
    {
        /// <summary>
        /// Creates <see cref="CmsPageBreadcrumbs"/> object for rendering page breadcrumbs
        /// </summary>
        /// <param name="htmlHelper">Current HtmlHelper</param>
        /// <param name="htmlAttributes">Attributes for wrapper element</param>
        /// <returns></returns>
        public static CmsPageBreadcrumbs PageBreadcrumbs(this HtmlHelper htmlHelper, object htmlAttributes = null)
        {
            return new CmsPageBreadcrumbs(htmlHelper).Attributes(htmlAttributes);
        }
    }

    /// <summary>
    /// Page breadcrumb builder.
    /// </summary>
    /// <remarks>By default renders ul li structure</remarks>
    public class CmsPageBreadcrumbs : CmsMvcBaseComponent<CmsPageBreadcrumbs, IEnumerable<CmsPageComponentItem>>
    {
        private CmsPage _targetPage;
        private readonly CmsPageService _pageService = new CmsPageService();
        private PlaceholderPagesMode placeholderPageMode = PlaceholderPagesMode.UsualPage;
        
        protected virtual CmsPage TargetPage
        {
            get
            {
                if (_targetPage == null)
                {
                    _targetPage = DependencyServiceLocator.Current.GetInstance<ICmsContext>().ContextPage;
                }

                return _targetPage;
            }
            set
            {
                _targetPage = value;
            }
        }

        protected override IEnumerable<CmsPageComponentItem> Value
        {
            get
            {
                var value = base.Value;

                if ((TargetPage != null) && (value == null))
                {
                    var data = _pageService.GetParentsPages(TargetPage.Id, true);

                    if (data != null)
                    {
                        var latestItem = data.LastOrDefault();

                        if (placeholderPageMode == PlaceholderPagesMode.Hide)
                        {
                            data = data.Where(p => p.BehaviourPageType != CmsPageBehaviourTypeKind.Placeholder);
                        }

                        value = data.SelectMany(
                            p =>
                                {
                                    var strategy = PagePresentStrategyFactory.GetStrategy(p);
                                    var res = new List<CmsPageComponentItem>();
                                    foreach (var item in strategy.GetBreadcrumbItems())
                                    {
                                        item.IsLatest = latestItem != null && item.PageId == latestItem.Id;
                                        if (item.PageBehaviourType == CmsPageBehaviourTypeKind.Placeholder && placeholderPageMode ==  PlaceholderPagesMode.NotClickable)
                                        {
                                            item.Url = null;
                                            item.IsLatest = true;
                                        }
                                        res.Add(item);
                                    }
                                    return res;
                                });                        

                        base.Value = value;
                    }
                }

                return value;
            }
        }

        public CmsPageBreadcrumbs(HtmlHelper htmlHelper)
            : base(htmlHelper)
        {
            Component = this;
            SetDefaultTemplate();
        }

        private void SetDefaultTemplate()
        {
            Wrapper(tag: "ul", htmlAttributes: new { @class = "b-breadcrumb__list" });
            InlineTemplate = p =>
                                 {
                                     var result = new StringBuilder();

                                     foreach(var item in p)
                                     {
                                         if (!item.IsLatest)
                                         {
                                             result.AppendFormat("<li class=\"b-breadcrumb__item\"><a class=\"b-breadcrumb__link\" href=\"{0}\">{1}</a></li><li class=\"b-breadcrumb__separator\">&gt;</li>", item.Url, item.Title);
                                         }
                                         else
                                         {
                                             result.AppendFormat("<li class=\"b-breadcrumb__item\">{0}</li>", item.Title);
                                         }
                                     }

                                     return result.ToString();
                                 };

        }

        /// <summary>
        /// Specifies current page for breadcrumbs.By default ICmsContext.ContentPage is used
        /// </summary>
        /// <param name="page">An object of CmsPage</param>
        /// <returns></returns>
        public CmsPageBreadcrumbs ForPage(CmsPage page)
        {
            if (page==null)
            {
                CancelRender = true;
            }

            TargetPage = page;

            return this;
        }

        /// <summary>
        /// Sets mode for rendering placeholder pages
        /// </summary>
        /// <param name="value">Mode to set</param>
        /// <returns></returns>
        public CmsPageBreadcrumbs PlaceholderPageMode(PlaceholderPagesMode value)
        {
            placeholderPageMode = value;
            return this;
        }
    }

    /// <summary>
    /// Presents modes for rendering placeholder pages
    /// </summary>
    public enum PlaceholderPagesMode
    {
        /// <summary>
        /// Renders as page with title and URL
        /// </summary>
        UsualPage,
        
        /// <summary>
        /// Does not render
        /// </summary>
        Hide,

        /// <summary>
        /// Renders as page with title only
        /// </summary>
        NotClickable
    }
}
